create or replace package body m4o_dbg as

  -- ===========================================================================
  p_hsecs     pls_integer;

  -- ===========================================================================
  --
  -- ----- PL/SQL Call Stack -----
  --   object      line  object
  --   handle    number  name
  --  3cc1acc        13  package body GE.M4O_DBG
  --  3cc1acc       153  package body GE.M4O_DBG
  --  3535570        16  package body GE.M4O_TRACE
  --         ^- here it starts to become interesting
  --  42422a0       802  package body GE.M4O_ATK
  --  3ffedd8         5  anonymous block
  -- 
  function callstack_level return pls_integer
  is
    v_stack varchar2(4000) := dbms_utility.format_call_stack;
    v_level pls_integer    := -4;
    v_pos   pls_integer    := 1;
  begin
    loop
      v_pos := instr(v_stack,m4o_v2.CR,v_pos);
      if v_pos > 0 then
        v_level := v_level + 1;
        v_pos   := v_pos   + 1;
      else
        exit;
      end if;
    end loop;

    return v_level;
  end;
  -- ===========================================================================
  function enabled return boolean
  is
  begin
    return p_level > 0;
  end;

  -- ===========================================================================
  procedure disable
  is
  begin
    enable(0);
  end;

  -- ===========================================================================
  -- enable debug for this session
  procedure enable(i_level in pls_integer := 2)
  is
  begin
    if p_level = 0 then
      p_hsecs := dbms_utility.get_time;
      dbms_output.enable;
    end if;
    p_level := i_level;
  end;

  -- ===========================================================================
  procedure p(
    i_str     in varchar2,
    i_uplevel in pls_integer := 0)
  is
    v_text varchar2(32767);
  begin
    if p_level > 0 then
      --dbms_output.put_line(dbms_utility.format_call_stack);
      v_text := lpad(dbms_utility.get_time-p_hsecs,6,'0')||
                '|'                                      ||
                lpad('+',callstack_level-i_uplevel,'+')  ||
                '|'                                      ||
                substr(i_str,1,3900);

      dbms_output.put_line(v_text);
    end if;
  end;
end;
/
